`timescale    1ns/100ps
module sys_reboot(
    input       wire            resetb      ,
    input       wire            sclk        , //125m
    
    input       wire            time_1s_sync    ,
    
    input  wire [3:0]       apb_sel              ,
    input  wire [31:0]      apb_addr             ,
    input  wire             apb_rw_en            ,
    input  wire [31:0]      apb_wdata            
);

wire                reboot_o_osc        ;
reg  [ 11: 0]       reboot_en_cnt       ;
reg                 reboot_en_delayed   ;
reg  [1:0]          reboot_sel          ;

reg                 reboot_en       ;
reg                 reboot_wr_en    ;
reg                 ext_cfg_wr      ;
reg                 reboot_flag     ;
reg     [1:0]       reboot_cnt      ;
reg                 reboot_en_tmp   ;


//************************************************/
//        reboot保护
//************************************************/
always @(posedge sclk or negedge resetb) begin
    if (!resetb)
        ext_cfg_wr <= 1'b0;
    else if (apb_sel[0] && apb_addr[27:16]==12'h200 && apb_rw_en)
        ext_cfg_wr <= 1'b1;
    else 
        ext_cfg_wr <= 1'b0;
end

always @(posedge sclk or negedge resetb) begin
    if (!resetb)
        reboot_wr_en <= 1'b0;
    else if (apb_sel[0] && apb_addr[27:16]==12'h300 && apb_rw_en)
        reboot_wr_en <= 1'b1;
    else 
        reboot_wr_en <= 1'b0;
end

always @(posedge sclk or negedge resetb) begin
    if (!resetb)
        reboot_flag <= 1'b0;
    else if (ext_cfg_wr && apb_addr[7:2] == 6'h01)
        reboot_flag <= 1'b1;
    else if (reboot_cnt == 2'd0)
        reboot_flag <= 1'b0;
end

always @(posedge sclk or negedge resetb) begin
    if (!resetb)
        reboot_cnt <= 2'b0;
    else if (ext_cfg_wr == 1 && apb_addr[7:2] == 6'h01)
        reboot_cnt <= 2'd3;
    else if (time_1s_sync && reboot_cnt != 2'b0)
        reboot_cnt <= reboot_cnt - 1'b1;
end

//************************************************/
//      reboot_sel
//************************************************/
always @(posedge sclk or negedge resetb)
    if (resetb == 0)
        reboot_sel <= 1'b0;
    else if (ext_cfg_wr == 1 && apb_addr[7:2] == 6'h01)
        reboot_sel <= apb_wdata[9:8];

always@(posedge sclk or negedge resetb)
    if (resetb == 0)
        reboot_en_tmp<=0;
    else if (reboot_wr_en == 1)
        reboot_en_tmp<=1;

always@(posedge sclk or negedge resetb)
    if (resetb == 0)
        reboot_en<=1'b0;
    else
        reboot_en<=reboot_en_tmp&&reboot_flag;
        
`ifdef ALTERA
`else
always @(posedge sclk)
    if (reboot_en)
        begin
        if (reboot_en_cnt != 12'hfff)
            reboot_en_cnt <= reboot_en_cnt + 1'b1;
        end
    else
        reboot_en_cnt <= 'd0;

always @(posedge sclk)
    reboot_en_delayed <= reboot_en_cnt == 12'hfff;

alta_boot reboot(
    .i_boot(reboot_en_delayed),
    .im_vector_sel(reboot_sel),
    .i_osc_enb(1'b1),
    .o_osc(reboot_o_osc) // 不能悬空
);
`endif

endmodule
`default_nettype wire